package com.bluetooth.lib.server;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.widget.Toast;

import com.bluetooth.lib.BluetoothUtil;
import com.bluetooth.lib.impl.BluetoothClientImpl;
import com.bluetooth.lib.impl.BluetoothServerImpl;
import com.bluetooth.lib.util.F;
import com.bluetooth.lib.util.L;

/**
 * 蓝牙服务端
 * */
@TargetApi(Build.VERSION_CODES.ECLAIR) @SuppressLint("NewApi") 
public class BluetoothServer implements BluetoothServerImpl{
	
	private String tag = "BluetoothServer";
	
	private BluetoothAdapter mBluetoothAdapter;
	private Context context;
	private ExecutorService pool;

	private BluetoothServerSocket serverSocket;

	private ListenConnectThread listenConnectThread;
	
	private volatile boolean serverRunning = true;
	private volatile boolean connectedRunning = true;

	private List<BluetoothSocket> recvSockets = new ArrayList<BluetoothSocket>();

//	private ListenUTFCallBack listenUTFCallBack;
//
//	private ListenDataCallBack listenDataCallBack;
//
//	private ListenFileCallBack listenFileCallBack;

	private ListenCallBack listenCallBack;
	

	public BluetoothServer(Context context){
		this.context = context;
		initBlueTooth();
		initThreadPool();
	}
	
	/**
	 * 初始化线程池
	 * */
	private void initThreadPool() {
		//获得cpu核心数量
		int size = Runtime.getRuntime().availableProcessors();
		pool = Executors.newFixedThreadPool(size*2);
	}

	/**
	 * 初始化蓝牙模块
	 * */
	@SuppressLint("NewApi") 
	private void initBlueTooth() {
		mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
		if(mBluetoothAdapter==null){
			Toast.makeText(context, "未找到蓝牙设备", Toast.LENGTH_LONG).show();
			return;
		}
		
		if(!mBluetoothAdapter.isEnabled()){
			//弹出对话框提示用户是后打开
//			Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//			startActivityForResult(enabler,REQUEST_ENABLE);
			//不做提示，强行打开
			mBluetoothAdapter.enable();
		}
		
		//设置蓝牙可见
		Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, BluetoothUtil.DISCOVERABLE_TIME); //3600为蓝牙设备可见时间
        context.startActivity(enable);
        
	}


//	/**
//	 * 监听消息 utf字符串
//	 * ListenUTFCallBack 和 ListenDataCallBack只能选择一种 不可同时监听两种
//	 * */
//	@Override
//	public void listen(ListenUTFCallBack call) {
//		L.i(tag, "开始监听");
//		this.listenUTFCallBack = call;
////		if(serverRunning){
////			shutDown();
////		}
//		listenConnectThread = new ListenConnectThread();
//		listenConnectThread.start();
//	}
//	
//	/**
//	 * 监听byte[]类型数据
//	 * */
//	@Override
//	public void listen(ListenDataCallBack call) {
//		L.i(tag, "开始监听");
//		this.listenDataCallBack = call;
////		if(serverRunning){
////			shutDown();
////		}
//		listenConnectThread = new ListenConnectThread();
//		listenConnectThread.start();
//	}
//	
//	/**
//	 * 接收文件
//	 * */
//	public void listen(ListenFileCallBack call){
//		this.listenFileCallBack = call;
////		if(serverRunning){
////			shutDown();
////		}
//		listenConnectThread = new ListenConnectThread();
//		listenConnectThread.start();
//	}
	
	@Override
	public void listen(ListenCallBack call){
		this.listenCallBack = call;
		listenConnectThread = new ListenConnectThread();
		listenConnectThread.start();
	}
	
	/**
	 * 关闭蓝牙服务端
	 * 关闭serverSocket 结束线程
	 * 关闭socket 结束线程
	 * */
	public void shutDown(){
		serverRunning = false;
		connectedRunning=false;
		for (BluetoothSocket  socket: recvSockets) {
			if(socket!=null){
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		recvSockets.clear();
		
		try {
			L.i(tag, "closeServerSocket");
			if(serverSocket!=null) serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 监听连接的线程
	 * */
	private class ListenConnectThread extends Thread{
		
		@SuppressLint("NewApi") 
		@Override
		public void run() {
			L.i(tag, "监听连接的线程执行");
			try {
				if(BluetoothUtil.SOCKET_TYPE==1){
					serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(tag, UUID.fromString(BluetoothUtil.UUID));
				}else{
					serverSocket = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(tag, UUID.fromString(BluetoothUtil.UUID));
				}
				while(serverRunning){
					L.i(tag, "循环监听消息");
					L.i(tag, "进入阻塞状态，等待接收连接");
					BluetoothSocket socket = serverSocket.accept();
					L.i(tag, "接收到连接");
					pool.execute(new ConnectedTask(socket));
					recvSockets.add(socket);
				}
				
				
			} catch (IOException e) {
				L.i(tag, "出现异常serverSocket："+e.getMessage());
				e.printStackTrace();
				try {
					serverSocket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		
	}
	
	
	
	/**
	 * 处理连接的线程
	 * */
	private class ConnectedTask implements Runnable{
		
		private BluetoothSocket socket;

		public ConnectedTask(BluetoothSocket socket){
			this.socket = socket;
		}
		
		@SuppressWarnings("resource")
		@Override
		public void run() {
			try {
				InputStream in = socket.getInputStream();
				OutputStream out = socket.getOutputStream();
				DataInputStream dis = new DataInputStream(in);
				DataOutputStream dos = new DataOutputStream(out);
				while(connectedRunning){
					L.i(tag, "循环读取数据");
					if(listenCallBack==null) return;
					int type = dis.readInt();
					if(type==BluetoothUtil.SEND_TYPE_UTF){//接收utf数据
						L.i(tag, "接收utf数据");
						String receiveData = dis.readUTF();
						L.i(tag, "收到："+receiveData);
						String s = listenCallBack.onRecvUTF(receiveData);
						if(s!=null&&!TextUtils.isEmpty(s)){
							dos.writeUTF(s);
						}
					}else if(type==BluetoothUtil.SEND_TYPE_DATA){//接收byte[]数据
						L.i(tag, "接收byte[]数据");
						long len = dis.readLong();//数据长度
						ByteArrayOutputStream baos = new ByteArrayOutputStream();
						byte[] buf = new byte[1024];
						long t = 0;
						int c;
						while((c=dis.read(buf))>0){
							baos.write(buf, 0, c);
							t+=c;
							L.i(tag, "读取数据中："+c+"|"+t);
							if(t==len) break;
						}
						L.i(tag, "读取数据完毕");
						byte[] data = baos.toByteArray();
						listenCallBack.onRecvData(data);
					}else if(type==BluetoothUtil.SEND_TYPE_FILE){//接收文件
						L.i(tag, "接收文件");
						long fileLen = dis.readLong();
						L.i(tag, "文件长度："+fileLen);
						String fileName = dis.readUTF();
						L.i(tag, "文件名："+fileName);
						String fileMd5 = dis.readUTF();
						L.i(tag, "文件名md5："+fileMd5);
						boolean isbreak = dis.readBoolean();
						L.i(tag, "是否使用断点续传："+isbreak);
						
						//创建文件存放目录
						String path = BluetoothUtil.BLUETOOTH_RECV_PATH;
						F.createDirs(path);
						
						//判断是否要进行断点续传
						File fileDir = new File(path);
						File[] listFile = fileDir.listFiles();
						File breakFile = null;
						if(isbreak){//使用断点续传再去检查是否有断点文件
							for (File f : listFile) {
								if(f.getName().startsWith(fileMd5)){
									breakFile = f;
								}
							}
						}
						
						if(breakFile==null){
							L.i(tag, "非断点续传");
							//发送断点位置
							dos.writeLong(0);
							//创建临时文件
							File tempFile = new File(path+"/"+fileMd5);
							if(!tempFile.exists()){
								tempFile.createNewFile(); 
							}else{
								F.delFile(tempFile.getAbsolutePath());
								tempFile.createNewFile(); 
							}
							L.i(tag, "临时文件："+tempFile.getAbsolutePath());
							FileOutputStream fos = new FileOutputStream(tempFile);
							byte[] buf = new byte[1024];
							long t = 0;
							int c;
							while((c=dis.read(buf))>0){
								t+=c;
								fos.write(buf, 0, c);
								L.i(tag, "接收文件中："+c+"|"+t);
								listenCallBack.onRecvingFile(t, fileLen);
								if(t==fileLen) break;
							}
							L.i(tag, "接收文完毕");
							//文件重命名
							File newFile = new File(path+"/"+fileName);
							tempFile.renameTo(newFile);
							L.i(tag, "重命名："+fileName);
							listenCallBack.onRecvFile(newFile);
						}else{
							L.i(tag, "断点续传");
							RandomAccessFile randomFile = new RandomAccessFile(breakFile, "rw");
							long breakFileLen = breakFile.length();
							L.i(tag, "断点文件长度："+breakFileLen);
							//发送断点位置
							dos.writeLong(breakFileLen);
							L.i(tag, "断点文件："+breakFile.getAbsolutePath());
							randomFile.seek(breakFileLen);
							byte[] buf = new byte[1024];
							long t = breakFileLen;
							int c;
							while((c=dis.read(buf))>0){
								randomFile.write(buf, 0, c);
								t+=c;
//								L.i(tag, "断点接收文件中："+c+"|"+t);
								listenCallBack.onRecvingFile(t, fileLen);
								if(t==fileLen) break;
							}
							L.i(tag, "断点接收文件完毕");
							File newFile = new File(path+"/"+fileName);
							breakFile.renameTo(newFile);
							L.i(tag, "重命名："+fileName);
							listenCallBack.onRecvFile(newFile);
						}
					}
				}
				
			} catch (IOException e) {
				L.i(tag, "出现异常socket："+e.getMessage());
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
	}
//	/**
//	 * 处理连接的线程
//	 * */
//	private class ConnectedTask implements Runnable{
//		
//		private BluetoothSocket socket;
//		
//		public ConnectedTask(BluetoothSocket socket){
//			this.socket = socket;
//		}
//		
//		@Override
//		public void run() {
//			try {
//				InputStream in = socket.getInputStream();
//				OutputStream out = socket.getOutputStream();
//				DataInputStream dis = new DataInputStream(in);
//				DataOutputStream dos = new DataOutputStream(out);
//				while(connectedRunning){
//					L.i(tag, "循环读取数据流");
//					if(listenUTFCallBack!=null){
//						String receiveData = dis.readUTF();
//						L.i(tag, "收到："+receiveData);
//						String s = listenUTFCallBack.onReceive(receiveData);
//						
//						if(!TextUtils.isEmpty(s)){
//							dos.writeUTF(s);
//						}
//						
//					}else if(listenDataCallBack!=null){
//						long len = dis.readLong();//数据总长度
//						long start = System.currentTimeMillis();
//						L.i(tag, "数据总长度："+len);
//						ByteArrayOutputStream baos = new ByteArrayOutputStream();
//						byte[] buf = new byte[1024];
//						long t = 0;
//						int c;
//						while((c=dis.read(buf))>0){
//							baos.write(buf, 0, c);
//							t+=c;
//							L.i(tag, "读取数据中："+c+"|"+t);
//							if(t==len) break;
//						}
//						byte[] data = baos.toByteArray();
//						long end = System.currentTimeMillis();
//						L.i(tag, "读取数据完毕："+data.length+"用时："+(end-start)+"ms | 速率："+((len)/((end-start)))+"byte/ms");
//						
//						listenDataCallBack.onReceive(data);
//						
//						socket.close();
//						break;
//					}else if(listenFileCallBack!=null){
//						L.i(tag, "接收文件");
//						String fileName = dis.readUTF();
//						L.i(tag, "文件名："+fileName);
//						String md5 = dis.readUTF();
//						L.i(tag, "文件名md5："+md5);
//						long len = dis.readLong();
//						L.i(tag, "文件长度："+len);
//						boolean isbreak = dis.readBoolean();
//						if(!isbreak){//此文件不需要断点续传功能
//							
//						}
//						
//						String path = BluetoothUtil.BLUETOOTH_RECV_PATH;
//						F.createDirs(path);
//						
//						//判断是否是断点续传
//						File fileDir = new File(path);
//						File[] listFile = fileDir.listFiles();
//						File breakFile = null;
//						for (File f : listFile) {
//							if(f.getName().startsWith(md5)){
//								breakFile = f;
//								if(!isbreak){//不使用断点续传
//									F.delFile(breakFile.getAbsolutePath());
//									breakFile = null;
//								}
//							}
//						}
//						
//						if(breakFile==null){
//							L.i(tag, "非断点续传");
//							dos.writeLong(0);
//							File file = new File(path+"/"+md5);
//							if(!file.exists()) file.createNewFile(); 
//							FileOutputStream fos = new FileOutputStream(file);
//							byte[] buf = new byte[1024];
//							long t = 0;
//							int c;
//							while((c=dis.read(buf))>0){
//								t+=c;
//								fos.write(buf, 0, c);
//								L.i(tag, "接收文件中："+c+"|"+t);
//								listenFileCallBack.onReceiving(t, len);
//								if(t==len) break;
//							}
//							L.i(tag, "接收文完毕");
//							//文件重命名
//							File newFile = new File(path+"/"+fileName);
//							file.renameTo(newFile);
//							L.i(tag, "重命名："+fileName);
//							listenFileCallBack.onReceive(newFile);
//						}else{//断点续传
//							L.i(tag, "断点续传");
//							RandomAccessFile randomFile = new RandomAccessFile(breakFile, "rw");
//							long fileLen = breakFile.length();
//							dos.writeLong(fileLen);
//							L.i(tag, "断点文件长度："+fileLen);
//							L.i(tag, "断点文件名字："+breakFile.getName());
//							randomFile.seek(fileLen);
//							byte[] buf = new byte[1024];
//							long t = fileLen;
//							int c;
//							while((c=dis.read(buf))>0){
//								randomFile.write(buf, 0, c);
//								t+=c;
//								L.i(tag, "断点接收文件中："+c+"|"+t);
//								listenFileCallBack.onReceiving(t, len);
//								if(t==len) break;
//							}
//							L.i(tag, "断点接收文件完毕");
//							File newFile = new File(path+"/"+fileName);
//							breakFile.renameTo(newFile);
//							L.i(tag, "重命名："+fileName);
//							listenFileCallBack.onReceive(newFile);
//						}
//						L.i(tag, "关闭socket");
//						socket.close();
//						break;
//						
//					}
//				}
//				
//			} catch (IOException e) {
//				L.i(tag, "出现异常socket："+e.getMessage());
//				try {
//					socket.close();
//				} catch (IOException e1) {
//					e1.printStackTrace();
//				}
//				e.printStackTrace();
//			}
//		}
//	}
	
//	/**
//	 * 监听utf消息的字符串
//	 * onReceive 返回null 对应sendUTF(String s)  
//	 * 返回非null或空 对应sendUTF(String msg, SendUTFCallBack call)
//	 * */
//	public interface ListenUTFCallBack{
//		String onReceive(String s);
//	}
//	
//	/**
//	 * 监听byte[]数组
//	 * */
//	public interface ListenDataCallBack{
//		void onReceive(byte[] data);
//	}
//	
//	/**
//	 * 监听文件传输
//	 * */
//	public interface ListenFileCallBack{
//		void onReceiving(long current, long total);
//		void onReceive(File f);
//	}
	
	public interface ListenCallBack{
		String onRecvUTF(String s);
		void onRecvData(byte[] data);
		void onRecvingFile(long current, long total);
		void onRecvFile(File file);
	}
	
	
}
